/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package linkeddata.arida.ufc.br.VCD;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import linkeddata.arida.ufc.br.manager.impl.BuildsMapJson;
import linkeddata.arida.ufc.br.manager.impl.CreateCacheXMLFile;
import linkeddata.arida.ufc.br.manager.impl.ExecuteQueryJena;
import linkeddata.arida.ufc.br.search.FileHierarchyVCDS;

/**
 *
 * @author jeovane
 */
public class ExecuteQueryVCDS {
    
    private ElementsVCDS elementsVCDS;
    private ExecuteQueryJena queryJena;
    private FileHierarchyVCDS fhv;
    private List<ExtractsContentVCD> sortList = new ArrayList<ExtractsContentVCD>();
    private Map filterQuery = new HashMap();
    private CreateCacheXMLFile createXMLFile;
    private String outMXL;
    
    public ExecuteQueryVCDS(ElementsVCDS elementsVCDS, FileHierarchyVCDS fhv, String jsonTextQuery) {
        this.elementsVCDS = elementsVCDS;
        this.fhv = fhv;
        this.sortList = sortList();
        this.outMXL = sortList.get(0).getVCDMain();
        this.filterQuery = filterQuery(jsonTextQuery);
    }

    // Ordena a lista de ExtractsContentVCD utilizando o algoritmos de busca em largura (BFS)
    private List<ExtractsContentVCD> sortList() {
        List<ExtractsContentVCD> sortListVCD = new ArrayList<ExtractsContentVCD>();
        for (String nodes : fhv.CorrectHierarchyVCDS()) {
            for (int i = 0; i < elementsVCDS.getExtractList().size(); i++) {
                if (elementsVCDS.getExtractList().get(i).getNameVCD().equalsIgnoreCase(nodes)) {
                    sortListVCD.add(elementsVCDS.getExtractList().get(i));
                }
            }
        }
        return sortListVCD;
    }

    // Obtém o tamanho da quantidade de parametros contido em cada Elos
    private int sizeDestinationVCD(ExtractsContentVCD e) {
        return e.getElosVCD().size();
    }

    // Obtém os parâmetros de cada VCD
    public List<String> extractDestinationVCD(int countClick) {
        List<String> eVCD = new ArrayList<String>();
        for (int i = 0; i < sortList.get(countClick).getElosVCD().size(); i++) {
            eVCD.add(sortList.get(countClick).getElosVCD().get(i).getParameter());
        }
        return eVCD;
    }

    // Obtém as VCDS que possuem destinos
    private List<String> getDestinationVCD(int countClick) {
        List<String> dVCD = new ArrayList<String>();
        
        for (int i = 0; i < sortList.size(); i++) {
            for (int j = 0; j < sizeDestinationVCD(sortList.get(i)); j++) {
                String destination = sortList.get(i).getElosVCD().get(j).getDestinationVCD();
                String varDestination = sortList.get(i).getElosVCD().get(j).getParameter();
                
                if (destination != null && destination.equalsIgnoreCase(sortList.get(countClick).getNameVCD())) {
                    dVCD.add(varDestination);
                }
            }
        }
        return dVCD;
    }
    
    private Map filterQuery(String jsonTextQuery) {
        return BuildsMapJson.JSONMap(jsonTextQuery);
    }

    // Constrói a query a ser executada de cada VCD
    public String getQueryVCD(int countClick) {
        String select = "";
        String query = "";
        String nameVCD = sortList.get(countClick).getNameVCD();

        // Obtém os PREFIXs das querys
        int prefixSize = sortList.get(countClick).extractQueryVCD().size();
        for (int i = 0; i < prefixSize; i++) {
            String prefix = sortList.get(countClick).extractQueryVCD().get(i).getPrefix();
            query += prefix + "\n";
        }

        // Constrói o SELECT da query
        select += "SELECT ";
        //ArrayList<String> selectQuery = sortList.get(countClick).getAttributesVCD().get(sortList.get(countClick).getNameVCD());
        List<String> selectQuery = sortList.get(countClick).getVariablesSelect();
        for (Iterator<String> it = selectQuery.iterator(); it.hasNext();) {
            String value = it.next();
            select += "?" + value + " ";
        }
        
        // Constrói o WHERE da query
        query += select + "\n" + "WHERE { \n";
        int whereSize = sortList.get(countClick).extractQueryVCD().size();
        String conditionWhere = "";
        for (int i = 0; i < whereSize; i++) {
            String service = sortList.get(countClick).extractQueryVCD().get(i).getService();
            String keyFilter = nameVCD + " ?:" + service;
            if (filterQuery.containsKey(keyFilter)) {
                for (Iterator it = filterQuery.entrySet().iterator(); it.hasNext();) {
                    Map.Entry entry = (Map.Entry) it.next();
                    LinkedList<String> linkedValues = (LinkedList<String>) entry.getValue();
                    String filter = "";
                    if (keyFilter.equals(entry.getKey())) {
                        for (String linked : linkedValues) {
                            filter += linked + "\n";
                        }
                        conditionWhere = sortList.get(countClick).extractQueryVCD().get(i).getWhere() + filter;
                    }
                }
            } else {
                conditionWhere = sortList.get(countClick).extractQueryVCD().get(i).getWhere();
            }
            
            query += "SERVICE <" + service + "> {\n"
                    + conditionWhere + " }\n";
            
        }
        query += "} " + sortList.get(countClick).getCondition() + " " + sortList.get(countClick).getLimit();
        query = query.replaceAll("\\s+", " ");
        
        return query;
    }

    // Executa a query de cada VCD
    public String executeQueryVCD(String valueClick, int countClick) throws Exception {
        queryJena = new ExecuteQueryJena(sortList.get(countClick).getServiceURI(), getQueryVCD(countClick));
        if (valueClick != null) {
            for (String vcde : getDestinationVCD(countClick)) {
                queryJena.setParameterList(vcde + "," + valueClick);
            }
        }
        return queryJena.printQueryJSON();
    }
    
    // Mostra as variáveis da próxima query a ser executada
    public List<String> pathBetweenVCDS(int countClick) throws Exception {
        List<String> varsQuery = new ArrayList<String>();
        
        countClick += 1;
        if (countClick < sortList.size()) {
            for (int i = countClick - 1; i <= countClick; i++) {
                varsQuery = sortList.get(countClick).getVariablesSelect();
            }
        }
        return varsQuery;
    }

    // Armazena os resultados das querys que já foram executadas
    public void queriesAlreadyExecuted(String valueClick, String getQuery, int countClick) throws Exception {
        File file = new File(System.getProperty("user.home") + "/" + System.getProperty("user.name") + "_" + outMXL + ".xml");
        
        if (!file.exists()) {
            createXMLFile = new CreateCacheXMLFile(outMXL);
            createXMLFile.createDocQuery(sortList.get(countClick).getNameVCD(), valueClick, getQuery);
        } else {
            if (!ElementsVCDS.getExistingKey().containsKey(valueClick)) {
                createXMLFile = new CreateCacheXMLFile(file, outMXL);
                createXMLFile.createDocQuery(sortList.get(countClick).getNameVCD(), valueClick, getQuery);
            }
        }
    }
    
    public Map<String, ArrayList<String>> getServices(int countClick) {
        return sortList.get(countClick).getServicesVCDS();
    }
}
